﻿using Azure;
using Dm;
using ServiceCore.DbContext;
using ServiceCore.Entity.Const;
using ServiceCore.Entity.Core;
using ServiceCore.Entity.Model;
using ServiceCore.Entity.Param;
using ServiceCore.Entity.Param.Map;
using System.Reflection;

namespace ServiceCore.Service
{
    /// <summary>
    /// 映射服务
    /// </summary>
    public partial class MapService : SqlsugarServices<MapInfo>
    {
        /// <summary>
        /// 分页 
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<MapInfo, List<MapInfo>> Map_List(BaseParam<MapInfo, List<MapInfo>> arg)
        {
            arg.Data = this.Context.Queryable<MapInfo>()
                .WhereIF(arg.Param != null && string.IsNullOrEmpty(arg.Param.MapType) == false, x => x.MapType == arg.Param.MapType)
                .WhereIF(arg.Param != null && arg.Param.DataId > 0, x => x.DataId == arg.Param.DataId)
                .WhereIF(arg.Param != null && string.IsNullOrEmpty(arg.Param.BindId) == false, x => x.BindId == arg.Param.BindId)
                .OrderBy(x => x.SortBy)
                .ToList();           
            if (arg.Data.Any() == false)
                return arg;

            arg.Data.ForEach(x => { x.MapTypeName = GlobalVar.GetEnumVal(x.MapType); x.BindName = GlobalVar.GetEnumVal(x.BindId); });

            if (arg.Param != null && string.IsNullOrEmpty(arg.Param.MapType) == false)
            {
                var tagTypeNames = new List<string>() { "ColorLargeType", "DirectionLargeType", "LuckyLargeType", "SeasonLargeType", "WorldLargeType" };
                var tagNames = new List<string>() { "ColorType", "FiveElemType" };
                if (tagTypeNames.Contains(arg.Param.MapType))
                { 
                    var tagTypeIds = arg.Data.Select(x => x.DataId).Distinct().ToList();
                    var tagTypes = this.Context.Queryable<TagTypeInfo>().Where(x => tagTypeIds.Contains(x.Id)).ToList();
                    arg.Data.ForEach(x => x.DataName = tagTypes.Where(n => n.Id == x.DataId).FirstOrDefault()?.Name);
                }
                else if (tagNames.Contains(arg.Param.MapType))
                {
                    var tagIds = arg.Data.Select(x => x.DataId).Distinct().ToList();
                    var tags = this.Context.Queryable<TagInfo, TagTypeInfo>((tag, tagType) => tag.TagTypeId == tagType.Id)
                        .Where((tag, tagType) => tagIds.Contains(tag.Id))
                        .Select((tag, tagType) => new TagInfo() 
                        {
                            Id = tag.Id,
                            Name = tag.Name,
                            TagTypeId = tagType.Id,
                            TagTypeName = tagType.Name
                        })
                        .ToList();
                    var tag = new TagInfo();
                    arg.Data.ForEach(x =>
                    {
                        tag = tags.Where(n => n.Id == x.DataId).FirstOrDefault();
                        if (tag != null)
                            x.DataName = $"{tag.TagTypeName}-{tag.Name}";
                    });
                }
            }

            arg.Param = null;
            return arg;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<List<MapInfo>, long> Map_SaveList(BaseParam<List<MapInfo>, long> arg)
        {
            arg = Map_SaveList_Verify(arg);
            if (string.IsNullOrEmpty(arg.ErrorMsg) == false)
                return arg;

            var MapType = arg.Param[0].MapType;
            var DataId = arg.Param[0].DataId;
            var BindId = arg.Param[0].BindId;
            if (string.IsNullOrEmpty(MapType) == false && DataId > 0)
                this.Context.Deleteable<MapInfo>().Where(x => x.MapType == MapType && x.DataId == DataId).ExecuteCommand();
            else if (string.IsNullOrEmpty(MapType) == false && string.IsNullOrEmpty(BindId) == false)
                this.Context.Deleteable<MapInfo>().Where(x => x.MapType == MapType && x.BindId == BindId).ExecuteCommand();

            this.Context.Insertable<MapInfo>(arg.Param).ExecuteCommand();

            arg.Param = null;
            return arg;
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<IdsParam, long> Map_DeleteList(BaseParam<IdsParam, long> arg)
        {
            arg = Map_DeleteList_Verify(arg);
            if (string.IsNullOrEmpty(arg.ErrorMsg) == false)
                return arg;

            arg.Data = this.Context.Deleteable<MapInfo>().Where(x => arg.Param.Ids.Contains(x.Id)).ExecuteCommand();
            arg.Param = null;

            return arg;
        }


        /// <summary>
        /// 分页 
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<MapTagParam, MapTagParam> Map_TagType_List(BaseParam<MapTagParam, MapTagParam> arg)
        {
            arg = Map_TagType_List_Verify(arg);
            if (string.IsNullOrEmpty(arg.ErrorMsg) == false)
                return arg;

            arg.Data = new MapTagParam();
            var lstBind = this.Context.Queryable<TagTypeInfo>()
                .OrderBy(x => x.CreateTime)
                .Select(x => new MapInfo() 
                {
                    MapType = arg.Param.MapType,
                    BindId = arg.Param.BindId,
                    DataId = x.Id,
                    DataName = x.Name,
                })
                .ToList();
            if (lstBind.Any() == false)
                return arg;

            var lstMapInfo = this.Context.Queryable<MapInfo>().Where(x => x.MapType == arg.Param.MapType).ToList();
            //if (lstMapInfo.Any() == false)
            //    return arg;

            arg.Data.lstDataId = lstMapInfo.Where(x => x.BindId == arg.Param.BindId).Select(x => x.DataId.ToString()).ToList();

            arg.Data.lstBind.AddRange(lstBind.Where(x => arg.Data.lstDataId.Contains(x.DataId.ToString())));
            var lstDataId = lstMapInfo.Select(x => x.DataId.ToString()).ToList();
            arg.Data.lstBind.AddRange(lstBind.Where(x => lstDataId.Contains(x.DataId.ToString()) == false));

            arg.Param = null;
            return arg;
        }

        /// <summary>
        /// 保存 
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<MapTagParam, int> Map_TagType_Save(BaseParam<MapTagParam, int> arg)
        {
            arg = Map_TagType_Save_Verify(arg);
            if (string.IsNullOrEmpty(arg.ErrorMsg) == false)
                return arg;

            this.Context.Deleteable<MapInfo>().Where(x => x.MapType == arg.Param.MapType && x.BindId == arg.Param.BindId).ExecuteCommand();
                        
            arg.Data = this.Context.Insertable<MapInfo>(arg.Param.lstBind).ExecuteCommand();

            arg.Param = null;
            return arg;
        }


        /// <summary>
        /// 分页 
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public BaseParam<MapTagParam, MapTagParam> Map_Tag_List(BaseParam<MapTagParam, MapTagParam> arg)
        {
            arg = Map_TagType_List_Verify(arg);
            if (string.IsNullOrEmpty(arg.ErrorMsg) == false)
                return arg;

            arg.Data = new MapTagParam();
            var lstBind = this.Context.Queryable<TagInfo, TagTypeInfo>((tag, tagType) => tag.TagTypeId == tagType.Id)
                .OrderBy((tag, tagType) => tagType.CreateTime)
                .OrderBy((tag, tagType) => tag.CreateTime)
                .Select((tag, tagType) => new MapInfo()
                {
                    MapType = arg.Param.MapType,
                    BindId = arg.Param.BindId,
                    DataId = tag.Id,
                    DataName = $"{tagType.Name}-{tag.Name}",
                })
                .ToList();
            if (lstBind.Any() == false)
                return arg;

            var lstMapInfo = this.Context.Queryable<MapInfo>().Where(x => x.MapType == arg.Param.MapType).ToList();
            //if (lstMapInfo.Any() == false)
            //    return arg;

            arg.Data.lstDataId = lstMapInfo.Where(x => x.BindId == arg.Param.BindId).Select(x => x.DataId.ToString()).ToList();

            arg.Data.lstBind.AddRange(lstBind.Where(x => arg.Data.lstDataId.Contains(x.DataId.ToString())));
            var lstDataId = lstMapInfo.Select(x => x.DataId.ToString()).ToList();
            arg.Data.lstBind.AddRange(lstBind.Where(x => lstDataId.Contains(x.DataId.ToString()) == false));

            arg.Param = null;
            return arg;
        }
    }
}
